#include"HttpServer.h"
#include"Config.h"
#include"Logger.h"
#include"Handler.h"
#include"Interceptor.h"
#include<algorithm>
using namespace wjc;
using namespace Log;
using namespace Http;

HttpServer::HttpServer(const net::InetAddress& serverAddr, const std::string& name) /*: server(Config::CorePoolSize, serverAddr, name)*/ {
    for (int i = 0; i < 1; ++i) {
        serversPtr.emplace_back(std::make_shared<TcpServer>(Config::CorePoolSize, serverAddr, name));
        serversPtr[i]->setMessageCallback(std::bind(&HttpServer::onMessage, this, serversPtr[i], std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
        serversPtr[i]->setConnectionCallback(std::bind(&HttpServer::onConnection, this, serversPtr[i], std::placeholders::_1));
    }
    init();
}

void HttpServer::init() {
    Interceptor inter;
    preIntercepters.push_back(std::bind(&Interceptor::AuthorityController, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    defaultHandler = std::bind(&Handler::handler, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    postIntercepters.push_back(std::bind(&Interceptor::PostInterceptor, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}

void HttpServer::onMessage(TcpServerPtr serverPtr, const ConnectionPtr& conn, BufferPtr& buff, Timestamp tm) {
    LOG_DEBUG << "onMessage enter:" << TimeHelper::consumeTime();
    std::shared_ptr<HttpProcessor> httpProcessorPtr = conn->getInMap<HttpProcessor>(HttpProcessorKey);
    assert(httpProcessorPtr);
    LOG_DEBUG << "onMessage process enter:" << TimeHelper::consumeTime();
    auto res = httpProcessorPtr->process();
    LOG_DEBUG << "onMessage process enter:" << TimeHelper::consumeTime();
    if (!res) 
        conn->setWriteCompleteCallback(std::bind(&HttpServer::onWriteComplete, this, serverPtr, std::placeholders::_1));
    LOG_DEBUG << "onMessage exit:" << TimeHelper::consumeTime();
}

void HttpServer::onWriteComplete(TcpServerPtr serverPtr, const ConnectionPtr& conn) {
    conn->close();
}

void HttpServer::onConnection(TcpServerPtr serverPtr, const ConnectionPtr& conn) {
    switch (conn->getState()) {
    case Connection::kConnected: {
        LOG_TRACE << conn->name() << " open the HttpConn !";
        std::shared_ptr<HttpProcessor> httpProcessorPtr = std::make_shared<HttpProcessor>(conn,shared_from_this());
        conn->putInMap(HttpProcessorKey, httpProcessorPtr);
        break;
    }
    case Connection::kDisconnected: {
        LOG_TRACE << conn->name() << " close the HttpConn !";
        conn->removeInMap(HttpProcessorKey);
        break;
    }
    default:
        break;
    }
}

void HttpServer::start() {
    for (int i = 0; i < serversPtr.size(); ++i) {
        serversPtr[i]->start();
    }
    std::string msg;
    while (std::getline(std::cin, msg)) {
        if (msg == "\\exit") {
            break;
        }
    }
    printf("hello from corenet!\n");
}
